//////////////////////////////////////////////////////////////////////////////////
//                                                                              //
//  This file is part of the buola project (https://code.google.com/p/buola/).  //
//                                                                              //
//  Copyright(c) 2007-2011 Xavi Gratal                                          //
//  gratal AT gmail DOT com                                                     //
//                                                                              //
//  Buola is free software: you can redistribute it and/or modify               //
//  it under the terms of the GNU General Public License as published by        //
//  the Free Software Foundation, either version 3 of the License, or           //
//  (at your option) any later version.                                         //
//                                                                              //
//  Buola is distributed in the hope that it will be useful,                    //
//  but WITHOUT ANY WARRANTY; without even the implied warranty of              //
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               //
//  GNU General Public License for more details.                                //
//                                                                              //
//  You should have received a copy of the GNU General Public License           //
//  along with buola.  If not, see <http://www.gnu.org/licenses/>.              //
//                                                                              //
//////////////////////////////////////////////////////////////////////////////////

#ifndef _BUOLA_UTILITY_CFPSMEASURE_H_
#define _BUOLA_UTILITY_CFPSMEASURE_H_

#include <buola/datetime/clocks.h>

namespace buola {

///\addtogroup utility
///@{
    
/////////////////////////////////////////////////////////////////////////////////////////////////

/// frame-rate monitor

/// Objects of this class allow to monitor the frame-rate of some process.
///
/// It keeps track of the average frame time, which is updated according to the formula:
/// \f[mean_n=(1-alpha) \cdot mean_{n-1}+alpha \cdot measurement\f]
/// every time a new measurement is available.
///
/// Then the frame rate is returned in frames per second as \f$ \frac{1}{mean} \f$
///
/////////////////////////////////////////////////////////////////////////////////////////////////
    
class CFPSMeasure
{
public:
    ///default constructor
    
    ///Upon construction, the frame start mark is set to the current time, so that the first time
    ///Frame() is called, it will set the frame rate according to the time between construction and
    ///the call. This can be changed by calling FrameStart() before calling Frame()
    ///
    ///\param pAlpha the rate of change of the measure
    CFPSMeasure(double pAlpha=0.05)
        :   mLast(CMonotonicClock::now())
        ,   mMean(-1.0)
        ,   mAlpha(pAlpha)
    {}

    ///adds a new measurement
    
    ///It updates the frame-rate to include this new measurement.
    void Frame(const chrono::nanoseconds &pDuration)
    {
        double lElapsed=to_double_seconds(pDuration);

        if(mMean<0)
            mMean=lElapsed;
        else
            mMean=(1-mAlpha)*mMean+mAlpha*lElapsed;
    }

    ///sets the frame start mark to the current time
    void FrameStart()
    {
        mLast=CMonotonicClock::now();
    }

    ///adds a new measurement
    
    ///It uses the time elapsed from the last frame start.
    ///
    ///It doesn't update the frame start mark
    void FrameEnd()
    {
        Frame(CMonotonicClock::now()-mLast);
    }

    ///adds a new measurement and sets the frame start mark
    
    ///This is equivalent to FrameEnd() followed by FrameStart(), but is more efficient since it saves a call
    ///to CClock::GetTime()
    void Frame()
    {
        CMonotonicTime lCurrent=CMonotonicClock::now();

        Frame(lCurrent-mLast);

        mLast=lCurrent;
    }

    ///returns the frame rate
    double Get()
    {
        return 1.0/mMean;
    }

private:
    CMonotonicTime mLast;
    double mMean;
    double mAlpha;
};

///@}

/*namespace buola*/ }

#endif
